# -*- coding:utf-8 -*-
# @Time: 2020/9/8 11:39
# @Author: gupeng
# @File: login_session.py
# @Desc: 登录会话--hset,hget,hdel测试

import random
from time import time
from hashlib import sha256

# 会话的默认过期时间
DEFAULT_TIMEOUT = 3600 * 24 * 30  # 一个月
# 存储会话令牌以及会话过期时间戳的散列
SESSION_TOKEN_HASH = 'session::token'
SESSION_EXPIRE_TS_HASH = 'session::expire_timestamp'
# 会话状态
SESSION_NOT_LOGIN = 'SESSION_NOT_LOGIN'
SESSION_EXPIRED = 'SESSION_EXPIRED'
SESSION_TOKEN_CORRECT = 'SESSION_TOKEN_CORRECT'
SESSION_TOKEN_INCORRECT = 'SESSION_TOKEN_INCORRECT'


def generate_token():
    random_string = str(random.getrandbits(256)).encode('utf-8')
    return sha256(random_string).hexdigest()


class LoginSession:
    def __init__(self, client, user_id):
        self.client = client
        self.user_id = user_id

    def create(self, timeout=DEFAULT_TIMEOUT):
        """
        创建新的登录会话
        :param timeout:会话过期时间（秒）
        :return:会话令牌
        """
        user_token = generate_token()
        expire_timestamp = time() + timeout
        self.client.hset(SESSION_TOKEN_HASH, self.user_id, user_token)
        self.client.hset(SESSION_EXPIRE_TS_HASH, self.user_id, expire_timestamp)
        return user_token

    def validate(self, input_token):
        """
        根据给定的令牌验证用户身份
        :param input_token: 令牌
        :return: 会话状态
                SESSION_NOT_LOGIN:用户尚未登录
                SESSION_EXPIRED:会话已过时
                SESSION_TOKEN_CORRECT:用户已经登录，并且会话匹配
                SESSION_TOKEN_INCORRECT:用户已登录，但会话不匹配
        """
        user_token = self.client.hget(SESSION_TOKEN_HASH, self.user_id)
        expire_timestamp = self.client.hget(SESSION_EXPIRE_TS_HASH, self.user_id)
        if (user_token is None) or (expire_timestamp is None):
            return SESSION_NOT_LOGIN
        if time() > float(expire_timestamp):
            return SESSION_EXPIRED
        if input_token == user_token.decode('utf-8'):
            return SESSION_TOKEN_CORRECT
        else:
            return SESSION_TOKEN_INCORRECT

    def destroy(self):
        """
        销毁会话
        :return:None
        """
        self.client.hdel(SESSION_TOKEN_HASH, self.user_id)
        self.client.hdel(SESSION_EXPIRE_TS_HASH, self.user_id)
